Developer Documentation

QuickTime 4 API Documentation

QuickTime 4 Reference

| Previous | Chapter Contents | Chapter Top | Next |

Creating Paths With Multiple Contours and Fills

Listing 4 shows how a single path shape can contain more than one path contour. The path shape defined in this example includes the round path from the previous example as well as a second round path, entirely contained within the first.

Listing 4 Creating a path with concentric contours

ComponentInstance vectorCodec;
Handle streamH;
Handle pathH;
gxPoint points[4];
Boolean isOnCurve[4];
int i;
long value;

/* open the vector codec component */
OpenADefaultComponent (decompressorComponentType,
                        kVectorCodecType, &vectorCodec);

/* create a new vector data stream */
CurveCreateVectorStream (vectorCodec, streamH);
value=gxClosedFrameFill

/* add an atom to the vector data stream that specifies that
   subsequent paths are to be drawn with closed frame fill */
CurveAddAtomToVectorStream (ci, kCurveFillTypeAtom,
                            sizeof(long), &value, streamH);

/* create the path */
CurveNewPath (vectorCodec, &pathH);

/* specify the points for the first contour and whether each one is
   on the path */
points[0].x = ff(50);
points[0].y = ff(50);
isOnCurve[0] = FALSE;
points[1].x = ff(150);
points[1].y = ff(50);
isOnCurve[1] = FALSE;
points[2].x = ff(150);
points[2].y = ff(150);
isOnCurve[2] = FALSE;
points[3].x = ff(50);
points[3].y = ff(150);
isOnCurve[3] = FALSE;

/* add the points for the first contour to the path */
for (i = 0; i <= 3; i++)
    CurveInsertPointIntoPath (vectorCodec, &points[i], pathH,
                              1, i, isOnCurve[i]);

/* specify the points for the second contour and whether each one is
   on the path */
points[0].x = ff(65);
points[0].y = ff(65);
isOnCurve[0] = FALSE;
points[1].x = ff(135);
points[1].y = ff(65);
isOnCurve[1] = FALSE;
points[2].x = ff(135);
points[2].y = ff(135);
isOnCurve[2] = FALSE;
points[3].x = ff(65);
points[3].y = ff(135);
isOnCurve[3] = FALSE;

/* add the points for the second contour to the path */
for (i = 0; i <= 3; i++)
    CurveInsertPointIntoPath (vectorCodec, &points[i], pathH,
                              2, i, isOnCurve[i]);

/* add the path to the vector data stream */
CurveAddPathAtomToVectorStream (vectorCodec, pathH, streamH);

/* mark the end of the vector data stream by adding a
   kCurveEndAtom atom to the stream */
CurveAddZeroAtomToVectorStream (vectorCodec, streamH);

/* use the vector codec here to decompress and display the vector data */

/* dispose of stream and path handles when done */
DisposeHandle (streamH);
DisposeHandle (pathH);

The result is shown in Figure 60 .

Figure 60 A path with two concentric clockwise contours and closed-frame fill

You can change the shape fill for this path by removing these lines from Listing 4 :

/* add an atom to the vector data stream that specifies that
   subsequent paths are to be drawn with closed frame fill */
CurveAddAtomToVectorStream (ci, kCurveFillTypeAtom, sizeof(long),
                            &value, streamH);

If you don't specify a fill type, you get the default fill type, which is the even-odd fill. The path shape resulting from an even-odd fill is shown in Figure 61 .

Figure 61 A path with two contours and even-odd shape fill

Notice that the even-odd shape fill causes the vector codec to fill in the outer contour, but not the inner contour. You can specify a winding fill by adding the following code before the code to draw a path:

/* add an atom to the vector data stream that specifies that
   subsequent paths are to be drawn with winding fill */
CurveAddAtomToVectorStream (ci, kCurveFillTypeAtom, sizeof(long),
                            &value, streamH);

The path drawn with a winding fill is shown in Figure 62 .

Figure 62 A path with two contours and winding fill

Unlike the even-odd shape fill, the winding shape fill causes the vector codec to fill inner contours -- as long as the inner contour has the same contour direction as the outer contour. If the inner contour and the outer contour have opposite contour directions, neither the even-odd shape fill nor the winding shape fill will fill the inner contour.

For example, if you change the direction of the inner contour from the previous example by reversing the order of the second contour's geometric points, as in the following code

/* specify the points for the second contour and whether each one is
   on the path */
points[0].x = ff(65);
points[0].y = ff(135);
isOnCurve[0] = FALSE;
points[1].x = ff(135);
points[1].y = ff(135);
isOnCurve[1] = FALSE;
points[2].x = ff(135);
points[2].y = ff(65);
isOnCurve[2] = FALSE;
points[3].x = ff(65);
points[3].y = ff(65);
isOnCurve[3] = FALSE;

/* add the points for the second contour to the path */
for (i = 0; i <= 3; i++)
    CurveInsertPointIntoPath (vectorCodec, &points[i], pathH,
                              2, i, isOnCurve[i]);

and you specify a closed-frame fill by adding the following code before the code to draw a path:

/* add an atom to the vector data stream that specifies that
   subsequent paths are to be drawn with winding fill */
CurveAddAtomToVectorStream (ci, kCurveFillTypeAtom, sizeof(long),
                            &value, streamH);

the resulting path has contours with opposite contour directions, as depicted in Figure 63 .

Figure 63 Path with internal counterclockwise contour and closed-frame fill

Since the outer contour and the inner contour have opposite contour directions, neither the even-odd shape fill nor the winding shape fill cause the vector codec to fill the inner contour, as shown in Figure 64 .

Figure 64 A path with even-odd or winding shape fill


© 1999 Apple Computer, Inc.

| Previous | Chapter Contents | Chapter Top | Next |